package org.dbi.mysql;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;

import org.dbi.beans.*;

import org.dbi.logger.ErrorLogger;

public class referentieleCheck {
	private ErrorLogger logger = ErrorLogger.getLogger(getClass().getName());
	
	public referentieleCheck() {
		
	}
	
	public boolean refCheckAlterTabel(ArrayList<Reference> refs, Tabel newTabel, Tabel oldTabel) {
		return false;
	}
	
	public boolean refCheckDropTable(Database currentDb, ArrayList<AttributeGroup> ownAttribGroups, ArrayList<Reference> refs) {
		boolean allCorrect = true;
		
		for (Reference ref : refs) {
			// Als iemand na mij verwijst mag ik niks. Eerst moeten alle
			// inkomende lijntjes weg.
			if (ownAttribGroups.contains(ref.getToGroup())) {
				
				if (allCorrect)
					allCorrect = false;
			}
		}
		
		return allCorrect;
	}
	
	public boolean refCheckDeleteRecords(Tabel ownTbl, Database currentDb, ArrayList<AttributeGroup> ownAttribGroups, ArrayList<Reference> refs, String[] columns, Object[] values) {
		boolean allCorrect = true;
		AttributeGroup from = null;
		AttributeGroup to = null;
		
		for (Reference ref : refs) {
			// Als ik naar een ander verwijs mag ik alles doen:)
			if (ownAttribGroups.contains(ref.getFromGroup())) {
				if (allCorrect)
					allCorrect = true;
			}
			// Als iemand van mij afhankelijk is moet ik oppassen wat ik weggooi
			if (ownAttribGroups.contains(ref.getToGroup())) {
				
				// Vind naar welke tabel naar mij verwijst: dit opslaan in
				// **toTabel**
				for (Tabel tbl : currentDb.getTabellen().values()) {
					for (Key key : tbl.getConstraint().getKeys().values()) {
						if (key.getAttributeGroups().values().contains(ref.getFromGroup())) {
							
							from = ref.getFromGroup();
							String[] customColumns = new String[from.getAttributes().values().size()];
							int x = 0;
							for (Attribute a : from.getAttributes().values()) {
								
								customColumns[x] = a.getNaam();
								x++;
								
							}
							
							if (tbl.selectSpecificColumnWithWhere(customColumns, customColumns, values).size() > 0) {
								logger.info("mag niet verwijderd worden. Er bestaan nog records in " + tbl.getNaam());
								if (allCorrect)
									allCorrect = false;
							} else {
								logger.info("Deze records mag verwijderd worden. Bestaat niet in tabel " + tbl.getNaam());
								ownTbl.deleteRecordWithWhere(columns, columns, values);
								if (allCorrect)
									allCorrect = true;
							}
						}
					}
				}
			}
		}
		return allCorrect;
	}
	
	public boolean refCheckInsertRecord(Database currentDb, ArrayList<AttributeGroup> ownAttribGroups, ArrayList<Reference> refs, String[] columns, Object[] values) {
		boolean allCorrect = true;
		AttributeGroup from = null;
		AttributeGroup to = null;
		Tabel toTabel = null;
		
		for (Reference ref : refs) {
			// Als iemand naar mij verwijst mag ik alles.. lekker puh
			if (ownAttribGroups.contains(ref.getToGroup())) {
				if (allCorrect)
					allCorrect = true;
			}
			// Als ik afhankelijk ben van een ander moet ik even kijken of dat
			// wel kan.
			if (ownAttribGroups.contains(ref.getFromGroup())) {
				
				// Vind naar welke tabel ik verwijs: dit opslaan in **toTabel**
				for (Tabel tbl : currentDb.getTabellen().values()) {
					//System.out.println(tbl.getNaam());
					for (Key key : tbl.getConstraint().getKeys().values()) {
						if (key.getAttributeGroups().values().contains(ref.getToGroup())) {
							toTabel = tbl;
							
							from = ref.getFromGroup();
							to = ref.getToGroup();
							
							// Maak een lijst met column ter grootte van de
							// attributen van de ToGroup
							String[] column = new String[to.getAttributes().values().size()];
							
							// In deze indexArray bijhouden welke indexen
							// overeenkomen
							ArrayList<Integer> index = new ArrayList<Integer>();
							
							// Iedere AttributeNaam die toGroup bevat in zelf
							// gemaakt columnArray zetten
							int x = 0;
							for (Attribute a : to.getAttributes().values()) {
								column[x] = a.getNaam();
								x++;
							}
							
							int intern = 0;
							// Kijk in de fromGroup welke attributes daarin
							// zitten en of die overeenkomen met de opgegeven
							// columnlijst
							// Zoja, toevoegen aan de index.
							for (Attribute a : from.getAttributes().values()) {
								for (int k = 0; k < columns.length; k++) {
									if (columns[k].equals(a.getNaam())) {
										index.add(k);
									}
								}
							}
							
							String[] value = new String[index.size()];
							
							// Voeg alle opgegeven values toe aan de
							// zelfgemaakte valueArray ahdv indexArray
							for (int i = 0; i < index.size(); i++) {
								value[i] = (String) values[index.get(i)].toString();
							}
							
							if (toTabel.selectSpecificColumnWithWhere(column, column, value).size() > 0) {
								if (allCorrect)
									allCorrect = true;
								logger.info("Record gevonden :). We gaan verder.");
							} else {
								logger.info("Record mag niet worden toegevoegd, omdat record niet bestaat in " + toTabel.getNaam());
								logger.info("Gevonden waarden" + Arrays.toString(columns) + " - "+ Arrays.toString(values));
								allCorrect = false;
							}
						}
					}
					
				}
			}
		}
		return allCorrect;
	}
	
	/**
	 * return value true = mag aanpassen, false = niet aanpassen
	 * 
	 * @param currentDB
	 * @param columns
	 * @param values
	 * @return
	 */
	
	public boolean refCheckUpdateRecord(PrimaryKey pk, ForeignKey fk, ArrayList<Reference> myRefs, String[] columnsToEdit) {
		ArrayList<Boolean> b = new ArrayList<Boolean>();
		for (int i = 0; i < columnsToEdit.length; i++) {
			b.add(refCheckUpdateRecord(pk, fk, myRefs, columnsToEdit[i]));
		}
		if (b.contains(false)) {
			return false;
		} else {
			return true;
		}
		
	}
	
	private boolean refCheckUpdateRecord(PrimaryKey pk, ForeignKey fk, ArrayList<Reference> myRefs, String s) {
		boolean canUpdate = true;
		for (Reference r : myRefs) {
			for (AttributeGroup ag : pk.getAttributeGroups().values()) {
				for (Attribute a : ag.getAttributes().values()) {
					if (a.getNaam().equals(s)) {
						logger.info(s + " is primary key waarde en kan niet aangepast worden.");
						canUpdate = false;
					}
				}
			}
		}
		return canUpdate;
	}
}